package main

import (
	"fmt"
	"sync"
)

// Counter 是一个线程安全的计数器
type Counter struct {
	mu    sync.Mutex
	count uint64
}

// Incr 对计数器进行加1操作
func (c *Counter) Incr() {
	c.mu.Lock() //使用了 `sync.Mutex` 进行保护，所以程序是线程安全的
	defer c.mu.Unlock()
	c.count++
}

// Get 获取当前计数器的值
func (c *Counter) Get() uint64 {
	c.mu.Lock() //使用了 `sync.Mutex` 进行保护，所以程序是线程安全的
	defer c.mu.Unlock()
	return c.count
}

func main() {
	// 1. 初始化一个 Counter 实例
	var counter Counter

	// 2. 使用 sync.WaitGroup 来等待所有 goroutine 完成
	var wg sync.WaitGroup

	// 3. 定义要启动的 goroutine 数量和每个 goroutine 的迭代次数
	const numGoroutines = 100
	const iterationsPerGoroutine = 1000

	// 4. 启动多个 goroutine 并发地增加计数器
	for i := 0; i < numGoroutines; i++ {
		// 为每个 goroutine 增加 WaitGroup 的计数
		wg.Add(1)

		// 启动 goroutine
		go func(goroutineID int) {
			// 在 goroutine 退出时，将 WaitGroup 的计数减 1
			defer wg.Done()

			// 每个 goroutine 执行 1000 次递增
			for j := 0; j < iterationsPerGoroutine; j++ {
				counter.Incr()
			}

			// 可选：打印每个 goroutine 完成的信息
			// fmt.Printf("Goroutine %d finished. Counter is now: %d\n", goroutineID, counter.Get())
		}(i) // 注意：这里将循环变量 i 作为参数传入，避免闭包引用问题
	}

	// 5. 等待所有 goroutine 完成它们的工作
	wg.Wait()

	// 6. 获取并打印最终的计数器值
	finalCount := counter.Get()
	fmt.Printf("最终的计数器值: %d\n", finalCount)

	// 7. 验证结果是否正确
	expectedCount := uint64(numGoroutines * iterationsPerGoroutine)
	fmt.Printf("验证结果是否正确: %v\n", expectedCount == finalCount)
}
